/*
  This file is part of JCM.

  JCM is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  JCM is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with JCM.  If not, see <http://www.gnu.org/licenses/>.
*/
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;

/**
 * Borda especializada de componente com transparência alfa.
*/
public class TransparentBorder extends AbstractBorder
{
  /**
   * Construtor da classe de borda especializada usando transparência alfa
   * dependente da opacidade do componente que a usuará declarada como
   * <b>false</b>.
  */
  public TransparentBorder()
  {
    super();
  }

  /**
   * Acessa o insets da borda do componente especificado.
   *
   * @param c Componente que usará a borda.
   * @return Insets da borda.
  */
  @Override public Insets getBorderInsets(Component c)
  {
    return insets;
  }

  /**
   * Reinicia o insets da borda do componente especificado.
   *
   * @param c Componente que usará a borda.
   * @param newInsets Insets do componente a reiniciar.
   * @return Insets da borda.
  */
  @Override public Insets getBorderInsets(Component c, Insets newInsets)
  {
    newInsets = insets;
    return super.getBorderInsets(c, newInsets);
  }

  /**
   * Renderiza a borda do componente na posição e dimensões do canvas.
   *
   * Observação: As operações com primitivas estão otimizadas devido
   *             ao número significativo de operações a cada vez que
   *             o componente se torna visível.
   *
   * @param c Componente menu que usará a borda.
   * @param g Canvas de renderização.
   * @param x Ordenada do canto superior esquerdo do canvas.
   * @param y Abicissa do canto superior esquerdo do canvas.
   * @param w Largura do canvas em pixels.
   * @param h Altura do canvas em pixels.
  */
  @Override public void paintBorder(Component c, Graphics g, int x, int y, int w, int h)
  {
    // obtêm os defaults do Look&Feel efetivo
    UIDefaults defaults = UIManager.getDefaults();

    // usa como cor da borda a cor da fonte do caractére de acessibilidade
    // no Look&Feel efetivo ou cinza claro se não declarada
    borderColor = (Color) defaults.get("Menu.acceleratorForeground");
    if (borderColor == null) borderColor = Color.LIGHT_GRAY;

    int x1, y1, w1, h1, w2, xa, ya;

    // renderiza completamente o contorno do componente com efeito 3D
    g.setColor(borderColor);
    g.drawRect(x, y, w1 = (w - 1), h1 = (h - 1));
    // usa cor de borda mais escura para efeito 3D
    g.setColor(borderColor = borderColor.darker());
    // borda inferior
    g.drawLine(xa = (x + w1), y1 = (y + 1), xa, ya = (y + h1));
    // borda direita
    g.drawLine(x1 = (x + 1), ya, xa, ya);

    // obtêm a cor de fundo default do menu no Look&Feel efetivo
    Color bgColor = (Color) defaults.get("Menu.background");

    // preenche completamente o canvas do componente contido dentro das
    // bordas mais externas com  default da cor de fundo transparente
    g.setColor(getTransparentColor(bgColor));
    g.fillRect(x1, y1, w2 = (w - 2), h - 2);

    reflexColor = (Color) defaults.get("MenuBar.highlight");
    if (reflexColor == null) reflexColor = Color.WHITE;

    // prepara a cor de preenchimento do reflexo 3D
    g.setColor(reflexColor);
    // reflexo 3D da borda superior dos itens
    g.drawLine(x + insets.left, y1, x + w2, y1);
  }

  /**
   * Instanciamento de objeto Color com canal de transparência a 87%.
   *
   * @param cor Objeto do tipo Color a derivar.
   * @return Objeto do tipo Color instanciado.
  */
  protected Color getTransparentColor(Color cor)
  {
    return new Color(cor.getRed(), cor.getGreen(), cor.getBlue(), 224);
  }

  /** Espaço mínimo reservado para a renderização das bordas. */
  protected Insets insets = new Insets(3, 1, 2, 1);

  /** Cor das bordas em alta exposição :: muita luminosidade. */
  protected Color borderColor;

  /** Cor do reflexo para efeito 3D e da etched border. */
  protected Color reflexColor;

  private static final long serialVersionUID = -2291154966433294950L;
}
